#include "include.h"

xcfg_cb_t xcfg_cb;
sys_cb_t sys_cb AT(.buf.bsp.sys_cb);
volatile int micl2gnd_flag;
volatile u32 ticks_50ms;
void sd_detect(void);
void tbox_uart_isr(void);
void testbox_init(void);
bool exspiflash_init(void);
void ledseg_6c6s_clr(void);
void mic_bias_var_init(void);
u8 usb_connect(void);

#if MIC_DETECT_EN
AT(.com_text.detect)
void mic_detect(void)
{
    if (IS_DET_MIC_BUSY()) {
        return;
    }
    if (MIC_IS_ONLINE()) {
        if (dev_online_filter(DEV_MIC)) {
            msg_enqueue(EVT_MIC_INSERT);
//            printf("mic insert\n");
        }
    } else {
        if (dev_offline_filter(DEV_MIC)) {
            msg_enqueue(EVT_MIC_REMOVE);
//            printf("mic remove\n");
        }
    }
}
#endif // EARPHONE_DETECT_EN
//AT(.com_text.const)
//const char usb_detect_str[] = "USB STA:%d\r\n";

#if USB_SUPPORT_EN
AT(.com_text.detect)
void usb_detect(void)
{
    if (!is_usb_support()) {
        return;
    }

    if(!sys_cb.bt_is_inited){
        return;
    }

#if (ADAPTER_USB_MIC_RX_EN)
//    u8 usb_sta = usbchk_connect(USBCHK_ONLY_DEVICE);
    u8 usb_sta= usb_connect();
    if (usb_sta == USB_PC_CONNECTED) {
        if (dev_online_filter(DEV_USBPC)) {
            msg_enqueue(EVT_PC_INSERT);
//            printf("pc insert\n");
        }
    } else {
        if (dev_offline_filter(DEV_USBPC)) {
            msg_enqueue(EVT_PC_REMOVE);
            pc_remove();
//            printf("pc remove\n");
        }
    }
#endif
}
#endif // USB_SUPPORT_EN

#if MICL_MUX_DETECT_LINEIN
AT(.com_text.detect)
bool linein_micl_is_online(void)
{
    if (!sys_cb.micl_en) {
        return (!(GPIOF & BIT(2)));
    } else {
        return (micl2gnd_flag);
    }
}
#endif // MICL_MUX_DETECT_LINEIN

#if LINEIN_DETECT_EN
AT(.com_text.detect)
void linein_detect(void)
{
    if (IS_DET_LINEIN_BUSY()) {
        return;
    }
    if (LINEIN_IS_ONLINE()) {
        if (dev_online_filter(DEV_LINEIN)) {
            msg_enqueue(EVT_LINEIN_INSERT);
//            printf("linein insert\n");
        }
    } else {
        if (dev_offline_filter(DEV_LINEIN)) {
            msg_enqueue(EVT_LINEIN_REMOVE);
//            printf("linein remove\n");
        }
    }
}
#endif // LINEIN_DETECT_EN


#if PWRKEY_2_HW_PWRON
//软开机模拟硬开关，松开PWRKEY就关机。
AT(.com_text.detect)
void pwrkey_2_hw_pwroff_detect(void)
{
    static int off_cnt = 0;
    if (!PWRKEY_2_HW_PWRON) {
        return;
    }

    if (IS_PWRKEY_PRESS()) {
        off_cnt = 0;
    } else {
        if (off_cnt < 10) {
            off_cnt++;
        } else if (off_cnt == 10) {
            //pwrkey已松开，需要关机
            off_cnt = 20;
            sys_cb.pwrdwn_hw_flag = 1;
            sys_cb.poweron_flag = 0;
        }
    }
}
#endif // PWRKEY_2_HW_PWRON

//timer tick interrupt(1ms)
AT(.com_text.timer)
void usr_tmr1ms_isr(void)
{
#if LED_DISP_EN
    port_2led_scan();
#endif // LED_DISP_EN

    plugin_tmr1ms_isr();
#if USER_KEY_KNOB2_EN
    bsp_key_scan();
#endif
}

//timer tick interrupt(5ms)
AT(.com_text.timer)
void usr_tmr5ms_thread(void)
{
    tmr5ms_cnt++;
#if LED_DISP_EN
    led_scan();
#endif
    //5ms timer process
    dac_fade_process();
#if !USER_KEY_KNOB2_EN
    bsp_key_scan();
#endif
#if PWRKEY_2_HW_PWRON
    pwrkey_2_hw_pwroff_detect();
#endif

#if VUSB_SMART_VBAT_HOUSE_EN
    bsp_vhouse_cmd_ack();
#endif
    plugin_tmr5ms_isr();

#if USB_SUPPORT_EN
    usb_detect();
#endif // USB_SUPPORT_EN

#if MIC_DETECT_EN
    mic_detect();
#endif // MIC_DETECT_EN

#if LINEIN_DETECT_EN
    linein_detect();
#endif // LINEIN_DETECT_EN

    //50ms timer process
    if ((tmr5ms_cnt % 10) == 0) {
        ticks_50ms++;
    }

    //100ms timer process
    if ((tmr5ms_cnt % 20) == 0) {
        lowpwr_tout_ticks();
#if UDE_HID_EN
        ude_tmr_isr();
#endif // UDE_HID_EN
        gui_box_isr();                  //显示控件计数处理

        if (sys_cb.lpwr_cnt > 0) {
            sys_cb.lpwr_cnt++;
        }

        if (sys_cb.key2unmute_cnt) {
            sys_cb.key2unmute_cnt--;
            if (!sys_cb.key2unmute_cnt) {
                msg_enqueue(EVT_KEY_2_UNMUTE);
            }
        }
    }

    //500ms timer process
    if ((tmr5ms_cnt % 100) == 0) {
        sys_cb.cm_times++;
    }

    //1s timer process
    if ((tmr5ms_cnt % 200) == 0) {
        msg_enqueue(MSG_SYS_1S);
        sys_cb.lpwr_warning_cnt++;
#if CHARGE_EN
        bsp_charge_bled_ctrl();
#endif // CHARGE_EN
    }
    //10s timer process
    if ((tmr5ms_cnt % 6000) == 0) {
        msg_enqueue(EVT_MSG_SYS_30S);
        tmr5ms_cnt = 0;
    }
}

AT(.com_text.bsp.sys)
void bsp_loudspeaker_mute(void)
{
    sys_cb.loudspeaker_mute = 1;
}

AT(.com_text.bsp.sys)
void bsp_loudspeaker_unmute(void)
{
    sys_cb.loudspeaker_mute = 0;
}

AT(.text.bsp.sys)
void bsp_sys_mute(void)
{
    if (!sys_cb.mute) {
        sys_cb.mute = 1;
        dac_fade_out();
        bsp_loudspeaker_mute();
    }
}

AT(.text.bsp.sys)
void bsp_sys_unmute(void)
{
    if (sys_cb.mute) {
        sys_cb.mute = 0;
        bsp_loudspeaker_unmute();
        dac_fade_in();
#if SYS_ADJ_DIGVOL_EN
        bool dac_diff_en = (DAC_CH_SEL == DAC_DIFF_MONO) || (DAC_CH_SEL == DAC_DIFF_DUAL);
        if (dac_diff_en) {
            dac_fade_wait();
            dac_anl_fade_sta_set(2);
        }
#endif
    }
}

AT(.text.bsp.sys)
void bsp_clr_mute_sta(void)
{
    if (sys_cb.mute) {
        sys_cb.mute = 0;
    }
}

AT(.com_text.bsp.sys)
bool bsp_get_mute_sta(void)
{
    return sys_cb.mute;
}

uint bsp_get_bat_level(void)
{
#if VBAT_DETECT_EN
    //计算方法：level = (实测电压 - 关机电压) / ((满电电压 - 关机电压) / 100)
    u16 bat_off = LPWR_OFF_VBAT * 100 + 2700;
    if (bat_off > sys_cb.vbat) {
        return 0;
    }
    uint bat_level = (sys_cb.vbat - bat_off) / ((4200 - bat_off) / 100);
//    printf("bat level: %d %d\n", sys_cb.vbat, bat_level);
    return bat_level;
#else
    return 100;
#endif
}

AT(.text.bsp.sys.init)
static void rtc_32k_configure(void)
{
    u32 temp = RTCCON0;
    temp &= ~BIT(6);                                //use RTC internal 32K osc
    temp |= BIT(2);                                 //CLK2M divide to RTC 32K clock source enable
    temp |= BIT(8);                                 //CLK2M in RTC power domain source select XOSC26M divide 8(3.25M)
    RTCCON0 = temp;
}

AT(.text.bsp.sys.init)
bool rtc_init(void)
{
    u32 temp;
    rtc_32k_configure();
    sys_cb.rtc_first_pwron = 0;
    temp = RTCCON0;
    if (temp & BIT(7)) {
        temp &= ~BIT(7);                            //clear first poweron flag
        RTCCON0 = temp;
        sys_cb.rtc_first_pwron = 1;
        printf("rtc 1st pwrup\n");
        return false;
    }

    return true;
}

//UART0打印信息输出GPIO选择，UART0默认G1(PA7)
void uart0_mapping_sel(void)
{
    //等待uart0发送完成
    if(UART0CON & BIT(0)) {
        while (!(UART0CON & BIT(8)));
    }

    GPIOADE  &= ~BIT(7);
    GPIOAFEN &= ~BIT(7);
    GPIOAPU  &= ~BIT(7);
    GPIOBFEN &= ~(BIT(2) | BIT(3));
    GPIOBPU  &= ~(BIT(2) | BIT(3));
    FUNCMCON0 = (0xf << 12) | (0xf << 8);           //clear uart0 mapping

#if (UART0_PRINTF_SEL == PRINTF_PA7)
    GPIOADE  |= BIT(7);
    GPIOAPU  |= BIT(7);
    GPIOADIR |= BIT(7);
    GPIOAFEN |= BIT(7);
    GPIOADRV |= BIT(7);
    FUNCMCON0 = URX0MAP_TX | UTX0MAP_PA7;           //RX0 Map To TX0, TX0 Map to G1
#elif (UART0_PRINTF_SEL == PRINTF_PB2)
    GPIOBDE  |= BIT(2);
    GPIOBPU  |= BIT(2);
    GPIOBDIR |= BIT(2);
    GPIOBFEN |= BIT(2);
    FUNCMCON0 = URX0MAP_TX | UTX0MAP_PB2;           //RX0 Map To TX0, TX0 Map to G2
#elif (UART0_PRINTF_SEL == PRINTF_PB3)
    GPIOBDE  |= BIT(3);
    GPIOBPU  |= BIT(3);
    GPIOBDIR |= BIT(3);
    GPIOBFEN |= BIT(3);
    FUNCMCON0 = URX0MAP_TX | UTX0MAP_PB3;           //RX0 Map To TX0, TX0 Map to G3
#elif (UART0_PRINTF_SEL == PRINTF_PE7)
    GPIOEDE  |= BIT(7);
    GPIOEPU  |= BIT(7);
    GPIOEDIR |= BIT(7);
    GPIOEFEN |= BIT(7);
    FUNCMCON0 = URX0MAP_TX | UTX0MAP_PE7;           //RX0 Map To TX0, TX0 Map to G4
#elif (UART0_PRINTF_SEL == PRINTF_PA1)
    GPIOADE  |= BIT(1);
    GPIOAPU  |= BIT(1);
    GPIOADIR |= BIT(1);
    GPIOAFEN |= BIT(1);
    FUNCMCON0 = URX0MAP_TX | UTX0MAP_PA1;           //RX0 Map To TX0, TX0 Map to G5
#elif (UART0_PRINTF_SEL == PRINTF_PE0)
    GPIOEDE  |= BIT(0);
    GPIOEPU  |= BIT(0);
    GPIOEDIR |= BIT(0);
    GPIOEFEN |= BIT(0);
    FUNCMCON0 = URX0MAP_TX | UTX0MAP_PE0;           //RX0 Map To TX0, TX0 Map to G6
#elif (UART0_PRINTF_SEL == PRINTF_PF2)
    GPIOFDE  |= BIT(0);
    GPIOFPU  |= BIT(0);
    GPIOFDIR |= BIT(0);
    GPIOFFEN |= BIT(0);
    FUNCMCON0 = URX0MAP_TX | UTX0MAP_PF2;           //RX0 Map To TX0, TX0 Map to G7
#elif (UART0_PRINTF_SEL == PRINTF_VUSB)
    FUNCMCON0 = URX0MAP_TX | UTX0MAP_VUSB;          //RX0 Map To TX0, TX0 Map to G8
#endif
}

//开user timer前初始化的内容
AT(.text.bsp.sys.init)
static void bsp_var_init(void)
{
    memset(&sys_cb, 0, sizeof(sys_cb));
    sys_cb.loudspeaker_mute = 1;
    sys_cb.ms_ticks = tick_get();
    sys_cb.pwrkey_5s_check = 1;
    xcfg_cb.vol_max = (xcfg_cb.vol_max) ? 32 : 16;
    sys_cb.init_vol         = (xcfg_cb.vol_max * xcfg_cb.sys_init_vol_perc + 50)/100;           //SYS_INIT_VOLUME
    sys_cb.recover_initvol  = (xcfg_cb.vol_max * xcfg_cb.sys_recover_initvol_perc + 50)/100;    //SYS_LIMIT_VOLUME
    sys_cb.warning_volume   = (xcfg_cb.vol_max * xcfg_cb.warning_volume_perc + 50)/100;         //WARNING_VOLUME
    sys_cb.sleep_time = -1L;
    sys_cb.pwroff_time = -1L;
    if (xcfg_cb.sys_sleep_time != 0) {
        sys_cb.sleep_time = (u32)xcfg_cb.sys_sleep_time * 10;   //100ms为单位
    }
    if (xcfg_cb.sys_off_time != 0) {
        sys_cb.pwroff_time = (u32)xcfg_cb.sys_off_time * 10;    //100ms为单位
    }

    sys_cb.sleep_delay = -1L;
    sys_cb.pwroff_delay = -1L;
    sys_cb.sleep_en = 0;
    sys_cb.lpwr_warning_times = LPWR_WARING_TIMES;
    sys_cb.wav_sysclk_bak = 0xff;

    key_var_init();
    plugin_var_init();

    msg_queue_init();

    dev_init(0 | ((u8)is_usb_support() * 0x02));
#if SD_SOFT_DETECT_EN
    if (SD_IS_SOFT_DETECT()) {
        dev_delay_times(DEV_SDCARD, 3);
    }
#endif

    sdadc_var_init();

//    music_stream_var_init();

    dac_cb_init((DAC_CH_SEL & 0x0f) | ((u8)DAC_LDOH_SEL << 4) | (0x200 * DAC_FAST_SETUP_EN) | (0x400 * DAC_VCM_CAPLESS_EN) | (0x800 * DACVDD_BYPASS_EN) | (0x1000 * DACRP_CH_VUSB_EN));
    mic_bias_var_init();

    mic_channel_init();
}

void tkey_sw_reset(void)
{
    RTCCON0 |= BIT(17) | BIT(4);
    INPCPND = BIT(0);                                       //inpwr_swrst
    asm("nop"); asm("nop");
    TKACON0 &= ~(BIT(23) | BIT(11));                        //disable TK channel
    TKACON1 &= ~(BIT(23) | BIT(11));

//    RTCCON0 |= BIT(4);
//    INPCPND = BIT(0);                                       //inpwr_swrst
//    RTCCON0 &= ~BIT(17);
}

AT(.text.bsp.sys.init)
static void bsp_io_init(void)
{
    GPIOADE = BIT(7);           //UART
    GPIOBDE = 0;
    GPIOEDE = 0;
    GPIOFDE = 0;
    GPIOGDE = 0x3F;             //MCP FLASH

    tkey_sw_reset();

    uart0_mapping_sel();        //调试UART IO选择或关闭

#if LINEIN_DETECT_EN
    LINEIN_DETECT_INIT();
#endif // LINEIN_DETECT_EN

#if MIC_DETECT_EN
    MIC_DETECT_INIT();
#endif

}

void bsp_get_xosc_xcfg(u8 *osci_cap, u8 *osco_cap, u8 *both_cap)
{
    *osci_cap = xcfg_cb.osci_cap;
    *osco_cap = xcfg_cb.osco_cap;
    *both_cap = xcfg_cb.osc_both_cap;
}

AT(.text.bsp.sys.init)
void bsp_update_init(void)
{
    /// config
    if (!xcfg_init(&xcfg_cb, sizeof(xcfg_cb))) {           //获取配置参数
        printf("xcfg init error\n");
    }

    // io init
    bsp_io_init();

    // var init
    bsp_var_init();
    sys_cb.lang_id = 0;

    // peripheral init
    rtc_init();
    param_init(sys_cb.rtc_first_pwron);

    //晶振配置
    xosc_init();

    plugin_init();
    sys_set_tmr_enable(1, 1);

    adpll_init(DAC_OUT_SPR);
    dac_init();
    mp3_res_play(RES_BUF_UPDATE_DONE_MP3, RES_LEN_UPDATE_DONE_MP3);
}

AT(.com_text.sys)
bool spiflash_speed_up_en(void)   //SPI FLASH提速。部份FLASH不支持提速
{
#if SPIFLASH_SPEED_UP_EN
    return true;
#else
    return false;
#endif
}



#if  0 //port_int_example
AT(.com_text)
const char strisr0[] = ">>[0x%X]_[0x%X]\n";
const char strisr1[] = "portisr->";
AT(.com_text.timer)
void port_isr(void)
{
    printf(strisr0,WKUPEDG,WKUPCPND);
    if (WKUPEDG & (BIT(6) << 16)) {
        WKUPCPND = (BIT(6) << 16);  //CLEAR PENDING
        printf(strisr1);
    }

}

void port_int_example(void)     //sys_set_tmr_enable(1, 1); 前调用 测试OK
{
    GPIOFDE |= BIT(0);  GPIOFDIR |= BIT(0); GPIOFFEN &= ~BIT(0);
    GPIOFPU |= BIT(0);
    sys_irq_init(IRQ_PORT_VECTOR,0, port_isr);
    PORTINTEN |= BIT(21);
    PORTINTEDG |= BIT(21);  //falling edge;
    WKUPEDG |= BIT(6);     //falling edge
    WKUPCON = BIT(6) | BIT(16);  //falling edge wake iput //wakeup int en

    printf("PORTINTEN = 0x%X, PORTINTEDG = 0x%X  WKUPEDG = 0x%X, WKUPCON = 0x%X\n", PORTINTEN, PORTINTEDG, WKUPEDG, WKUPCON);
    WDT_CLR();
    while(1) {
//       printf("WKUPEDG = 0x%X\n", WKUPEDG);
//       printf("GPIOF = 0x%X\n", GPIOF);
//       delay_ms(500);
    }
}
#endif
/*
AT(.com_rodata.isr)
const char str_t3[] = "T3 ";

AT(.com_text.isr)
void timer3_isr(void)
{
    if (TMR3CON & BIT(16)) {
        TMR3CPND = BIT(16);              //Clear Pending
    }
    printk(str_t3);
}
void timer3_init(void)
{
    CLKGAT1 |= BIT(8);
    delay_us(1);
	TMR3CON =  BIT(7);                  //Timer overflow interrupt enable
	TMR3CNT = 0;
	TMR3PR  = 2000000 / 2 - 1;          //500ms, select xosc26_div 1M clk
	TMR3CON |= BIT(2) | BIT(0);         //Timer works in Counter Mode
    sys_irq_init(IRQ_TMR3_VECTOR, 0, timer3_isr);
}

*/

#if !(VUSB_SMART_VBAT_HOUSE_EN || IODM_TEST_MODE)
AT(.text.sys_clk)
void update_uart1baud_in_sysclk_set(u32 baudrate){}  //关闭智能充电仓，切换系统频率不重新设置uart1波特率
#endif

#define MIC_DET_PIN1 7  //PA7
AT(.text.bsp.wireless_cb)
void wireless_mic_ctl1(u8 onoff)
{
	GPIOADE|= BIT(MIC_DET_PIN1);
	GPIOADIR&= ~BIT(MIC_DET_PIN1);
	if(onoff)
	{
		GPIOASET= BIT(MIC_DET_PIN1);
	}
	else
	{
		GPIOACLR= BIT(MIC_DET_PIN1);
	}
	
}

AT(.text.bsp.sys.init)
void bsp_sys_init(void)
{
    /// config
    if (!xcfg_init(&xcfg_cb, sizeof(xcfg_cb))) {           //获取配置参数
        printf("xcfg init error\n");
    }

    // io init
    bsp_io_init();
	wireless_mic_ctl1(0);
    // var init
    bsp_var_init();

    // power init
    pmu_init(BUCK_MODE_EN);

    // pll init
    adpll_init(DAC_OUT_SPR);

    // clock init
    set_sys_clk(SYS_CLK_SEL);
    // peripheral init
    rtc_init();
    param_init(sys_cb.rtc_first_pwron);
    //晶振配置
    xosc_init();

    plugin_init();

    if (POWKEY_10S_RESET) {
        RTCCON10 |= BIT(10);        //clear 10s pending
        RTCCON12 = 0;               //10S Reset Enable
        RTCCON0 |= BIT(8);
    } else {
        RTCCON12 = 0x0a;            //10S Reset Disable
    }
    led_init();
    key_init();


#if RF_EXT_CTL_EN
    RF_CTL_INIT();
#endif
    wireless_mic_var_init();
#if HUART_EN
    if(xcfg_cb.huart_en){
        bsp_huart_init();
    }
#endif // HUART_EN
    power_on_check();               //在key_init之后
    gui_init();
#if LED_DISP_EN
    sys_cb.led_sta = LED_USER_POWER_ON;
#endif
    gsensor_init();
    en_auto_pwroff();

    /// enable user timer for display & dac
    sys_set_tmr_enable(1, 1);


    gui_display(DISP_POWERON);

    bt_init();
//    if (bsp_dac_off_for_bt_conn()) {
//        dac_init();
////        func_bt_init();
//    } else {
////        func_bt_init();
//        dac_init();
//
//    }

    if (wireless_role_is_adapter()) {
        dac_init();
    } else {
#if DEVICE_DAC_OUTPUT_EN || WIRELESS_MIC_LOCAL_OUTPUT_EN
        dac_init();
#else
        adc_init_without_dac();
#endif
    }

#if RF_PWR_BALANCE_EN
    if (wireless_role_is_adapter()) {
        void btrf_power_balance_init(void);
        btrf_power_balance_init();
    }
#endif // RF_PWR_BALANCE_EN

	printf("sys_cb.vol:%d\n",sys_cb.vol);
	sys_cb.vol=25;
    bsp_change_volume(sys_cb.vol);

#if 0
    if ((xcfg_cb.bt_outbox_voice_pwron_en) || (!sys_cb.outbox_pwron_flag)) {
        mp3_res_play(RES_BUF_POWERON_MP3, RES_LEN_POWERON_MP3);
    }
    sys_cb.outbox_pwron_flag = 0;
#endif // WARNING_POWER_ON
    mic_bias_trim();

    func_cb.sta = FUNC_BT;

#if SYS_MODE_BREAKPOINT_EN
    u8 sta = param_sys_mode_read();
    if (sta != 0 && sta != 0xff) {
        func_cb.sta = sta & 0xf;
        if (func_cb.sta == FUNC_MUSIC) {
            sys_cb.cur_dev = sta >> 4;
        }
    }
#endif // SYS_MODE_BREAKPOINT_EN

#if LINEIN_2_PWRDOWN_EN
    if (dev_is_online(DEV_LINEIN)) {
        sys_cb.pwrdwn_tone_en = LINEIN_2_PWRDOWN_TONE_EN;
        func_cb.sta = FUNC_PWROFF;
    }
#endif // LINEIN_2_PWRDOWN_EN

#if EQ_DBG_IN_UART
    eq_dbg_init();
#endif // EQ_DBG_IN_UART

#if PLUGIN_SYS_INIT_FINISH_CALLBACK
    plugin_sys_init_finish_callback(); //初始化完成, 各方案可能还有些不同参数需要初始化,预留接口到各方案
#endif

    if (xcfg_cb.spk_mute_en) {
        u8 io_num = xcfg_cb.spk_mute_io_sel;
        gpio_t mute_gpio;
        gpio_t *p = &mute_gpio;
        bsp_gpio_cfg_init(p, io_num);
        if (p->sfr == NULL) {
            return;
        }
        p->sfr[GPIOxDE] |= BIT(p->num);
        p->sfr[GPIOxDIR] &= ~BIT(p->num);
        if (xcfg_cb.high_mute) {
            p->sfr[GPIOxCLR] = BIT(p->num);
        } else {
            p->sfr[GPIOxSET] = BIT(p->num);
        }
    }

}

